# -*- coding: utf-8 -*-
"""
 ----------------------------------------
|File Name:     compress_pdf             |
|Author:        WYT                      |
|date:          2020/6/8                 |
 ----------------------------------------
|  Change Activity:                      |
|                   2020/6/8:            |
-----------------------------------------
"""
import math
import os
import platform
from glob import glob
from pdf2image import convert_from_path
import fitz

from settings import base_path

# base_path = os.path.dirname(__file__).replace("\\", "/")
# /screen 供屏幕查看，与 Acrobat Distiller 的 "Screen Optimized" 类似，图片 72 dpi
# /ebook 与 Acrobat Distiller "eBook" 类似，图片 150 dpi
# /printer 高质量，与 Acrobat Distiller "Print Optimized" 类似，图片 300 dpi
# /prepress 高质量、颜色保真，与 Acrobat Distiller "Prepress Optimized" 类似、图片 300 dpi


class CompressPdfWithG():
    gs_exe_path = "{}\\gs9.52\\bin\\gswin64c.exe".format(base_path)

    def __init__(self, file_path="", max_size="", web_type=""):
        self.file_path = file_path
        self.quit = False
        if not file_path:
            self.quit = True
            return
        tu = os.path.split(file_path)
        self.save_path = tu[0]
        self.save_name = tu[1]
        # suffix 后缀
        filename, file_suffix = os.path.splitext(self.save_name)
        self.filename = filename
        self.file_suffix = file_suffix

        self.web_type = web_type
        if max_size == "" or max_size is None or float(max_size) <= 0:
            raise ValueError("pleaseenter the correct max_size value")
        if type(max_size) == str:
            max_size = float(max_size) if "." in max_size else int(max_size)
        self.max_size = max_size * 1024 * 1024
        # print(self.save_name, self.file_suffix, self.filename)

    # 不使用level 压缩文件时只使用 dpi 参数 , level=""
    @classmethod
    def get_command(cls, gs_exe_path="", dpi=None, out_file_path="", file_path=""):
        args = ["{}".format(gs_exe_path), "-sDEVICE=pdfwrite", "-dNOPAUSE", "-dBATCH", "-dQUIET", "-dNoUserUnit",
                "-dCompatibilityLevel=1.4", "-sOutputFile={}".format(out_file_path), "{}".format(file_path)]
        if dpi != None:
            smaller = ["-dDownsampleColorImages=true", "-dDownsampleGrayImages=true", "-dDownsampleMonoImages=true",
                       "-dColorImageResolution={}".format(dpi), "-dGrayImageResolution={}".format(dpi),
                       "-dMonoImageResolution={}".format(dpi)]
            for i, param in enumerate(smaller):
                args.insert(8 + i, param)
        return " ".join(args)

    @classmethod
    def rename(cls, old, new):
        while True:
            try:
                os.rename(old, new)
            except Exception as err:
                pass
            else:
                break

    # , level=None
    # 不使用level 压缩文件时只使用 dpi 参数
    def compress(self, dpi=None):
        if self.quit is True:
            return
        file_path = self.file_path
        out_file_path = "{}\\{}{}".format(self.save_path, "{}_compress".format(self.filename.replace(".pdf","")), self.file_suffix)
        file_size = os.path.getsize(file_path)
        max_size = self.max_size
        # out_file_size = None
        if os.path.exists(out_file_path):
            out_file_size = os.path.getsize(out_file_path)
            if out_file_size < max_size:
                os.remove(file_path)
                self.rename(old=out_file_path, new=file_path.replace(".pdf.pdf", ".pdf"))
                return
        # mulriple 多样的， 倍数
        mulriple = math.ceil(file_size / max_size)
        if dpi is None:
            if mulriple > 6:
                dpi = 72
            else:
                dpi = 150
        else:
            if self.web_type != "ctp":
                dpi -= 5
            else:
                dpi -= 10

        com = self.get_command(gs_exe_path=self.gs_exe_path, dpi=dpi, out_file_path=out_file_path, file_path=file_path)
        # print(com)
        # print()
        # f = os.popen(com)
        # subprocess.Popen(com)
        os.system(com)
        # print(f)
        # 递归调用该方法
        self.compress(dpi=dpi)


class CompressPdf():

    def __init__(self, file_path="", max_size="", web_type=""):
        self.file_path = file_path
        self.quit = False
        if not file_path:
            self.quit = True
            return
        tu = os.path.split(file_path)
        self.save_path = tu[0]
        self.save_name = tu[1]
        # suffix 后缀
        filename, file_suffix = os.path.splitext(self.save_name)
        self.filename = filename
        self.file_suffix = file_suffix

        self.web_type = web_type
        if max_size == "" or max_size is None or float(max_size) <= 0:
            raise ValueError("pleaseenter the correct max_size value")
        if type(max_size) == str:
            max_size = float(max_size) if "." in max_size else int(max_size)
        self.max_size = max_size * 1024 * 1024
        # print(self.save_name, self.file_suffix, self.filename)

    def img_pdfs(self, path='', img_path_list=[]):
        """把图片转换成pdf
        f_size: int, 压缩目标，KB
        quality: int, 初始压缩比率
        """
        img_path = '/'.join(path.replace('\\', '/').split('/')[0:-1])
        # path = path.replace('\\', '/').replace('.pdf', '_1.pdf')
        path = path.replace('\\', '/')
        doc = fitz.open()
        images = glob(img_path + f'//*.png')
        buslic = "{}\\buslic.png".format(self.save_path.replace("\\", "/"))
        if buslic in images:
            images.remove("{}\\buslic.png".format(self.save_path.replace("\\", "/")))
        image_list = [i.replace(img_path, "").replace("\\", "") for i in images]
        image_list.sort(key=lambda x: int(x.split("_")[0]))
        for img in image_list:
            img = img_path + '/' + img
            imgpdf = fitz.open('pdf', fitz.open(img).convertToPDF())
            doc.insertPDF(imgpdf)  # 将当前页插入pdf文档
            os.remove(img)
        doc.save(path)  # 保存pdf文件
        doc.close()
        return path

    def compress(self):
        pdfPath = self.file_path
        size = self.max_size
        if ".pdf.pdf" in pdfPath:
            res = pdfPath.replace(".pdf.pdf", ".pdf")
        else:
            res = pdfPath
        if os.path.isfile(res):
            if int(os.path.getsize(res)) < int(size):
                return
        if '.pdf' not in pdfPath:
            pdfPath = glob(pdfPath + f'//*.pdf')
        else:
            pdfPath = [pdfPath]
        for pdf in pdfPath:
            mb = 1920
            # base_path = os.path.abspath('').replace("\\", '/') + "/materials/"
            poppler_path = "{}\\poppler\\Library\\bin".format(base_path)
            system = platform.system()
            if system == 'Linux':
                poppler_path = None
            # pdf_path = base_path + "GR20214068341.pdf"
            pdf_path = pdf.replace('\\', '/')
            basePath = pdf_path.replace(pdf_path.split('/')[-1], '')
            pdf_path_name = pdf_path.replace(base_path, "")
            img_path_name = pdf_path_name.replace(".pdf.pdf", ".png")
            while True:
                img_list = []
                pages = convert_from_path(
                    pdf_path=pdf_path,
                    thread_count=50,
                    transparent=True,
                    poppler_path=poppler_path,
                    size=(mb, None)
                )
                # 保存
                p = 1
                for page in pages:
                    path, name = os.path.split(img_path_name)
                    img_path = basePath + f'{p}_{img_path_name}'
                    img_path = basePath + f"{p}_{name}"
                    page.save(img_path, 'JPEG')
                    img_list.append(img_path)
                    p += 1
                if ".pdf.pdf" in pdf_path:
                    ys_path = self.img_pdfs(pdf_path.replace('.pdf.pdf', 'a.pdf'))
                else:
                    ys_path = self.img_pdfs(pdf_path.replace('.pdf', 'a.pdf'))
                ys_size = os.path.getsize(ys_path)
                if int(ys_size) >= int(size):
                    mb -= 100
                else:
                    os.remove(pdf_path)
                    os.rename(ys_path, ys_path.replace('a.pdf', '.pdf'))
                    break


if __name__ == '__main__':
    gs_exe_path = "{}\\gs9.52\\bin\\gswin64c.exe".format(base_path)
    file_path = "C:\\Users\\Administrator\\Desktop\\pdf_test\\1pdf40683420216.pdf"
    # file_path = "C:\\Users\\Administrator\\Desktop\\GR_181831\\sta_detail.pdf"
    # file_path = "{}\\materials\\GR_2021\\ctp\\GR_955117\\otheratt.pdf.pdf".format(base_path)
    print(file_path)

    CompressPdf(file_path=file_path, max_size="9", web_type="320000").compress()

